package com.sunsharing.flow.model.node;

import com.sunsharing.common.Cache;
import com.sunsharing.common.anno.AnoClassCretator;
import com.sunsharing.common.anno.Factory;
import com.sunsharing.common.config.Config;
import com.sunsharing.dispatch.Dispatch;
import com.sunsharing.flow.exe.ExecutionContext;
import com.sunsharing.flow.exe.Token;
import com.sunsharing.flow.model.Node;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created with IntelliJ IDEA.
 * User: criss
 * Date: 13-5-19
 * Time: 下午4:42
 * To change this template use File | Settings | File Templates.
 */
@Factory(key="AndJoin")
public class AndJoin extends Node {
    private static Map<String,Lock> taskLock = new HashMap<String,Lock>();
    static Lock initlock = new ReentrantLock();
    static Cache cache = (Cache)AnoClassCretator.getInstance().createObject(Cache.class,"simple");
    /**
     * 功能描述:
     *     执行
     */
    public void execute(ExecutionContext executeContext) {

        logger.debug("进入AndJoin节点[" + this.getId() + "]");

        //获得token
        Token token = executeContext.getToken();
        String andForkNode = token.getAndForkNode();
        if(!Config.getInstance().getNodeId().equals(andForkNode))
        {
            //跑回Andfork节点合并
            Dispatch dispatch = new Dispatch();
            dispatch.setToNode(andForkNode);
            dispatch.run(token.getContext());
            return;
        }
        String andTaskId = token.getAndForkTaskId();
        initlock.lock();
        if(taskLock.get(andTaskId)==null)
        {
            taskLock.put(andTaskId,new ReentrantLock());
        }
        initlock.unlock();
        //合并Tocken
        Lock tl = taskLock.get(andTaskId);
        tl.lock();
        try
        {
            Token parTocken = (Token)cache.get(andTaskId);
            if(parTocken==null)
            {
                cache.put(andTaskId,token.getParent(),"300");
            } else
            {
                //tok.getParent().addChild(token);
                //token.setParent(tok);
                Iterator iter = parTocken.getChildren().values().iterator();
                while (iter.hasNext()) {
                    Token concurrentToken = (Token) iter.next();
                    if(concurrentToken.getName().equals(token.getName()))
                    {
                        concurrentToken.setChildPar(token.getChildPar());
                        concurrentToken.getContext().setHistory(token.getContext().getHistory());
                        token = concurrentToken;
                        break;
                    }
                }
            }
            token.setEndNode(this);
            //设置结束时间
            token.end();

            //获得父token
            Token parentToken = token.getParent();
            if (parentToken != null) {

                //循环子token,如果有的子token没有完成,则直接返回
                Iterator iter = parentToken.getChildren().values().iterator();
                parentToken.getContext().setHistory("");
                System.out.println("......."+parentToken.getChildren().values().size());
                while (iter.hasNext()) {
                    Token concurrentToken = (Token) iter.next();
                    if (!concurrentToken.hasEnded()) {
                        return;
                    }
                    parentToken.getContext().addHistory(concurrentToken.getContext().getHistory()+"||");
                }
                //删除Lock
                taskLock.remove(andTaskId);
                cache.remove(andTaskId);
                logger.error(taskLock.keySet().size());

                //把当前节点加入执行节点
                parentToken.addExecutedNode(this);
                //如果所有的token都已经完成,则激活父token
                ExecutionContext parentContext = new ExecutionContext(parentToken);
                logger.debug("离开AndJoin节点[" + this.getId() + "]");
                parentToken.getContext().printHistory();
                leave(parentContext);

            } else {
                throw new RuntimeException("And汇聚节点配置错误,应该与And发散节点配合使用!");
            }

        }catch (Exception e)
        {
            logger.error("AndJoin出错",e);
            throw new RuntimeException("AndJoin出错");
        }finally {
            tl.unlock();

        }





    }
}
